home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / emit.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  9KB  |  392 lines

  1. /*
  2.  * @(#)emit.c    1.6  1/20/89
  3.  */
  4. #include "assert.h"
  5. #include "genutils.h"
  6. #include "nodes.h"
  7. #include "builtins.h"
  8. #include "regdefs.h"
  9. #include "flags.h"
  10. #include "trace.h"
  11. #include "consts.h"
  12. #include "sequence.h"
  13.  
  14. Boolean doGenerateCode = 1;
  15.  
  16. /*VARARGS1*/
  17. void emit(format, args)
  18. char *format;
  19. int args;
  20. {
  21.   if (doGenerateCode) _doprnt(format, &args, codeFile);
  22.   IFTRACE(emit, 1) _doprnt(format, &args, stdout);
  23. }
  24.  
  25. Boolean isPush(d)
  26. DD d;
  27. {
  28.   if (d.kind != DD_Address) return(FALSE);
  29.   if (d.value.address.base != regs_sp) return(FALSE);
  30.   return (d.value.address.autoDecrement);
  31. }
  32.  
  33. Boolean isMemory(d)
  34. DD d;
  35. {
  36.   if (d.kind != DD_Address) return(FALSE);
  37.   return(d.value.address.base != Register);
  38. }
  39.  
  40. Boolean isAddressRegister(d)
  41. DD d;
  42. {
  43. #ifdef sun
  44.   static int addressRegs = 0xf033;
  45. #endif
  46. #ifdef vax
  47.   static int addressRegs = 0xffff;
  48. #endif
  49.   if (d.kind != DD_Address) return(FALSE);
  50.   if (d.value.address.base != Register) return(FALSE);
  51.   return(addressRegs & (1 << d.value.address.offset));
  52. }
  53.  
  54. Boolean isDataRegister(d)
  55. DD d;
  56. {
  57. #ifdef sun
  58.   static int dataRegs = 0x0fcc;
  59. #endif
  60. #ifdef vax
  61.   static int dataRegs = 0xffff;
  62. #endif
  63.   if (d.kind != DD_Address) return(FALSE);
  64.   if (d.value.address.base != Register) return(FALSE);
  65.   return(dataRegs & (1 << d.value.address.offset));
  66. }
  67.  
  68. Boolean isRegisterDD(d)
  69. DD d;
  70. {
  71.   if (d.kind != DD_Address) return(FALSE);
  72.   return(d.value.address.base == Register);
  73. }
  74.  
  75. Boolean isAppropriateRegister(d, brand)
  76. DD d;
  77. Brand brand;
  78. {
  79.   return ((brand == DataBrand && isDataRegister(d)) ||
  80.       (brand == ODPBrand  && isAddressRegister(d)));
  81. }
  82.  
  83. Boolean isManifestDD(d)
  84. DD d;
  85. {
  86.   return(d.kind == DD_Manifest || d.kind == DD_RealManifest);
  87. }
  88.  
  89. static void outDD(d, c)
  90. DD d;
  91. char c;
  92. {
  93.   writeDD(d, c);
  94.   IFTRACE(emitmove, 1) displayDD(stdout, d, c);
  95. }
  96.  
  97. /*VARARGS1*/
  98. static void out0(s)
  99. char *s;
  100. {
  101.   emit(s);
  102.   TRACE0(emitmove, 1, s);
  103. }
  104.  
  105. /*VARARGS1*/
  106. static void out1(s, x)
  107. char *s;
  108. int x;
  109. {
  110.   emit(s, x);
  111.   TRACE1(emitmove, 1, s, x);
  112. }
  113.  
  114. /*VARARGS1*/
  115. static void out2(s, x, y)
  116. char *s;
  117. int x, y;
  118. {
  119.   emit(s, x, y);
  120.   TRACE2(emitmove, 1, s, x, y);
  121. }
  122.  
  123. /*VARARGS1*/
  124. static void out3(s, x, y, z)
  125. char *s;
  126. int x, y, z;
  127. {
  128.   emit(s, x, y, z);
  129.   TRACE3(emitmove, 1, s, x, y, z);
  130. }
  131.  
  132. void emitMoveAddress(from, to)
  133. DD from, to;
  134. {
  135.   assert(!DDNeedsLabel(from));
  136.   assert(from.kind == DD_Address);
  137. #ifdef vax
  138.   out0("\tmoval\t");
  139. #endif
  140. #ifdef sun
  141.   out0("\tlea\t");
  142. #endif
  143.   outDD(from, ',');
  144.   outDD(to, '\n');
  145.   wroteCode = TRUE;
  146. }
  147.  
  148. void emitMove(from, to, size)
  149. DD from, to;
  150. char size;
  151. {
  152.   int trueLabel, endLabel;
  153.   DD intermediate;
  154.  
  155.   if (isSameDD(from, to)) return;
  156.   assert(to.kind == DD_Address);
  157.   if (DDNeedsLabel(from)) {
  158.     currentInstruction = nextLabelNumber++;
  159.     out1("L_%d:\t", currentInstruction);
  160.   } else {
  161.     out0("\t");
  162.   }
  163.   
  164.   if (from.kind == DD_PSLCondition) {
  165. #ifdef vax
  166.     if (FALSE) {
  167. #endif
  168. #ifdef sun
  169.     if (isDataRegister(to) && size == 'l') {
  170.       emit("%ss%s\t", JF(from.value.condition.isFloat),
  171.     JN(from.value.condition.psl));
  172.       writeDD(to, '\n');
  173.       emit("\textbl\t");
  174.       writeDD(to, '\n');
  175.       emit("\tnegl\t");
  176.       writeDD(to, '\n');
  177. #endif
  178.     } else {
  179.       trueLabel = nextLabelNumber++;
  180.       endLabel = nextLabelNumber++;
  181.       out3("%sb%s\tL_%d\n", JF(from.value.condition.isFloat),
  182.     JN(from.value.condition.psl), trueLabel);
  183.       intermediate.kind = DD_Manifest;
  184.       intermediate.value.manifest = 0;
  185.       emitMove(intermediate, to, size);
  186.       out2("\tj%s\tL_%d\n", JN(ALWAYS), endLabel);
  187.       out1("L_%d:\n", trueLabel);
  188.       intermediate.value.manifest = 1;
  189.       emitMove(intermediate, to, size);
  190.       out1("L_%d:\n", endLabel);
  191.     }
  192.   } else if (from.kind == DD_Self) {
  193.     assert(size == 'l');
  194.     trueLabel = nextLabelNumber++;
  195.     endLabel = nextLabelNumber++;
  196.     emitBranchOnBit(ODTag_global, 's', regs_g, buildLabelDD(trueLabel));
  197.     intermediate = buildRegisterDD(regs_g);
  198.     emitMove(intermediate, to, size);
  199.     emit("\tj%s\tL_%d\n", JN(ALWAYS), endLabel);
  200.     emit("L_%d:\n", trueLabel);
  201.     intermediate = buildRegisterDD(regs_b);
  202.     emitMove(intermediate, to, size);
  203.     emit("L_%d:\n", endLabel);
  204. #ifdef vax
  205.   } else if (from.kind == DD_Manifest && from.value.manifest == 0) {
  206. #endif
  207. #ifdef sun
  208.   } else if (from.kind == DD_Manifest && from.value.manifest == 0 &&
  209.          !isAddressRegister(to)) {
  210. #endif
  211.     out1("clr%c\t", size);
  212.     outDD(to, '\n');
  213. #ifdef vax
  214.   } else if (size == 'l' && isPush(to) && from.kind != DD_RealManifest) {
  215.     if (from.kind == DD_Label) {
  216.       /* use pushal */
  217.       out0("pushal\t");
  218.       outDD(from, '\n');
  219.     } else {
  220.       /* use pushl */
  221.       out0("pushl\t");
  222.       outDD(from, '\n');
  223.     }
  224. #endif
  225. #ifdef sun
  226.   } else if (size == 'l' && isPush(to) && from.kind == DD_Label) {
  227.     /* use pea */
  228.     out0("pea\t");
  229.     outDD(from, '\n');
  230. #endif
  231.   } else if (from.kind == DD_RealManifest) {
  232.     assert(size == 'l' || size == 'f');
  233. #ifdef vax
  234.     out1("movf\t");
  235. #endif
  236. #ifdef sun
  237.     out1("movl\t");
  238. #endif
  239.     outDD(from, ',');
  240.     outDD(to, '\n');
  241.   } else if (from.kind == DD_Label) {
  242. #ifdef vax
  243.     out1("moval\t");
  244.     outDD(from, ',');
  245.     outDD(to, '\n');
  246. #endif
  247. #ifdef sun
  248.     if (isAddressRegister(to)) {
  249.       out0("lea\t");
  250.       outDD(from, ',');
  251.       outDD(to, '\n');
  252.     } else {
  253.       out0("pea\t");
  254.       outDD(from,'\n');
  255.       out0("\tmovl\t");
  256.       outDD(popper, ',');
  257.       outDD(to, '\n');
  258.     }
  259. #endif
  260.   } else {
  261. #ifdef sun
  262.     if (from.kind == DD_Manifest && isDataRegister(to) && 
  263.     inRange(from.value.manifest, -128, 127) && size == 'l') {
  264.       out1("moveq\t");
  265.     } else {
  266.       out1("mov%c\t", size);
  267.     }
  268. #endif
  269. #ifdef vax
  270.     out1("mov%c\t", size);
  271. #endif
  272.     outDD(from, ',');
  273.     outDD(to, '\n');
  274.   }
  275.   wroteCode = TRUE;
  276. }
  277.  
  278. /*VARARGS1*/
  279. void Comment(format, args)
  280. char *format;
  281. int args;
  282. {
  283.   if (doGenerateCode) {
  284.     fprintf(codeFile, " %c ", COMMENTCHAR);
  285.     _doprnt(format, &args, codeFile);
  286.     (void) fputc('\n', codeFile);
  287.   }
  288.   IFTRACE(emit, 1) {
  289.     fprintf(stdout, " %c ", COMMENTCHAR);
  290.     _doprnt(format, &args, stdout);
  291.     (void) fputc('\n', stdout);
  292.   }
  293. }
  294.  
  295. writeStringData(s)
  296. char *s;
  297. {
  298.   int extra;
  299.   extra = 4 - (strlen(s) % 4);
  300.   if (extra == 4) extra = 0;
  301.   emit("\t.ascii\t\"");                    /* data */
  302.   for (; *s; s++) {
  303.     if (*s == '"') {
  304.       emit("\\\"");
  305.     } else if (*s == '\\') {
  306.       emit("\\\\");
  307.     } else if (*s >= ' ' && *s <= '~') {
  308.       emit("%c",*s);
  309.     } else {
  310.       emit("\\%03o", *s);
  311.     }
  312.   }
  313.   for (; extra; extra--) {
  314.     emit("\\000");
  315.   }
  316.   emit("\"\n");
  317. }
  318.  
  319. void emitStringObject(s, labelNumber, extraString, extraNumber)
  320. register char *s;
  321. int labelNumber;
  322. char *extraString;
  323. int extraNumber;
  324. {
  325.   ODTag tag;
  326.   tag = BuildTag(LOTag, TRUE);
  327.   tag.gcDoNotCollect = TRUE;
  328.   /* write the codeoid here to facilitate garbage collection */
  329.   writeHexComment(currentCodeOID, "Code OID containing this String");
  330.   if (extraString != NULL) emit("L_%s:\n", extraString);
  331.   emit("L_%d:", labelNumber);
  332.   writeTag(tag);                    /* tag */
  333.   writeHex((unsigned)0xabcdef01);            /* codePtr */
  334.   saveRelocationInfo(labelNumber, 4, AR_OIDToCodePtr,
  335.     OIDOfBuiltin(B_INSTCT, STRINGINDEX), 0);
  336.   writeData(0);                        /* ownOID */
  337.   writeData(strlen(s));                    /* sizeInBytes */
  338.   writeStringData(s);
  339. }
  340.  
  341. void emitVectorObject(vector, labelNumber, elementTypeSize, vecCodeOID)
  342. NodePtr vector;
  343. int labelNumber, elementTypeSize;
  344. OID vecCodeOID;
  345. {
  346.   ODTag tag;
  347.   int nElements, extra;
  348.   Variable v;
  349.   char *labelname;
  350.   NodePtr p;
  351.   tag = BuildTag(LOTag, TRUE);
  352.   tag.gcDoNotCollect = TRUE;
  353.   /* write the codeoid here to facilitate garbage collection */
  354.   writeHexComment(currentCodeOID, "Code OID containing this Vector");
  355.   emit("L_%d:", labelNumber);
  356.   writeTag(tag);                    /* tag */
  357.   writeHex((unsigned)0xabcdef01);            /* codePtr */
  358.   saveRelocationInfo(labelNumber, 4, AR_OIDToCodePtr, vecCodeOID, 0);
  359.   writeData(0);                        /* ownOID */
  360.   nElements = Sequence_Length(vector->b.vectorlit.exp);
  361.   writeData(nElements - 1);                /* upb */
  362.   writeData(nElements * elementTypeSize);        /* sizeInBytes */
  363.   extra = 4 - ((nElements * elementTypeSize) % 4);
  364.   if (extra == 4) extra = 0;
  365.   labelname = elementTypeSize == 1 ? ".byte" : ".long";
  366.  
  367.   Sequence_For(p, vector->b.vectorlit.exp)
  368.     vPushValue(p, pusherContext);
  369.     v = vPop();
  370.     switch (v.data.kind) {
  371.       case DD_Manifest:
  372.     emit("\t%s\t%d\n", labelname, v.data.value.manifest);
  373.     break;
  374.       case DD_Label:
  375.     emit("\t%s\tL_%d\n", labelname, v.data.value.label);
  376.     break;
  377.       default:
  378.     assert(FALSE);
  379.     break;
  380.     }
  381.     if (elementTypeSize == 8) {
  382.       writeHex((unsigned)0xabcdef01);            /* codePtr */
  383.       saveRelocationInfo(labelNumber, IMVector_data + (z__z * 8) + 4,
  384.     AR_OIDOIDToAbCon, getDDAbstractType(v.abCon),
  385.     getDDConcreteType(v.abCon));
  386.     }
  387.   Sequence_Next
  388.   for (; extra; extra--) {
  389.     emit("\t%s\t0\n", labelname);
  390.   }
  391. }
  392.